home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / misc / 40 / save.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-07-17  |  8.9 KB  |  363 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* save.c - version 1.0.3 */
  3.  
  4. #include <stdio.h>
  5. #include "hack.h"
  6. extern char genocided[60];    /* defined in Decl.c */
  7. extern char fut_geno[60];    /* idem */
  8. #ifdef UNIX
  9. #include <signal.h>
  10. #endif UNIX
  11.  
  12. extern char SAVEF[], nul[];
  13. extern char pl_character[PL_CSIZ];
  14. extern long lseek();
  15. extern struct obj *restobjchn();
  16. extern struct monst *restmonchn();
  17.  
  18. dosave(){
  19.     if(dosave0(0)) {
  20.         settty("Be seeing you ...\n");
  21.         exit(0);
  22.     }
  23. #ifdef lint
  24.     return(0);
  25. #endif lint
  26. }
  27.  
  28. #ifndef NOSAVEONHANGUP
  29. hangup(){
  30.     (void) dosave0(1);
  31.     exit(1);
  32. }
  33. #endif NOSAVEONHANGUP
  34.  
  35. /* returns 1 if save successful */
  36. dosave0(hu) int hu; {
  37.     register fd, ofd;
  38.     int tmp;        /* not register ! */
  39. #ifdef DGK
  40.     long free, needed;
  41. #endif DGK
  42.  
  43. #ifdef UNIX
  44. #ifdef SIGHUP
  45.     (void) signal(SIGHUP, SIG_IGN);
  46. #endif
  47.     (void) signal(SIGINT, SIG_IGN);
  48. #endif
  49.  
  50. #ifdef DGK
  51.     if (!saveDiskPrompt(0))
  52.         return 0;
  53.     /* Check to make sure there is enough space on the save disk.
  54.      * The extra 20000L is a conservative estimate of the amount
  55.      * of space necessary for the player's inventory plus an
  56.      * additional amount in case this level is not yet on disk.
  57.      * It would be much better to actually count the space necessary.
  58.      */
  59.     free = freediskspace(SAVEF);
  60.     needed = all_files_size(lock);
  61.     if (free < needed) {
  62.         pline("There is not enough disk space to save your game.");
  63.         return 0;
  64.     } else if (free < needed + 20000L) {
  65.         pline("There may not be enough disk space to save your game.");
  66.         pline("Do you want me to try saving the game anyway [y/n] ?");
  67.         fflush(stdout);
  68.         if (getchar() != 'y') {
  69.             docrt();
  70.             return 0;
  71.         }
  72.     }
  73. #endif DGK
  74.     if((fd = creat(SAVEF, FMASK)) < 0) {
  75.         if(!hu) pline("Cannot open save file. (Continue or Quit)");
  76.         (void) unlink(SAVEF);        /* ab@unido */
  77.         return(0);
  78.     }
  79.     if(flags.moonphase == FULL_MOON)    /* ut-sally!fletcher */
  80.         u.uluck--;            /* and unido!ab */
  81. #ifdef DGK
  82.     home();
  83.     cl_end();
  84.     printf("Saving level: %d", dlevel);
  85.     fflush(stdout);
  86. #endif DGK
  87.     savelev(fd,dlevel);
  88.     saveobjchn(fd, invent);
  89.     saveobjchn(fd, fcobj);
  90.     savemonchn(fd, fallen_down);
  91.     tmp = getuid();
  92.     bwrite(fd, (char *) &tmp, sizeof tmp);
  93.     bwrite(fd, (char *) &flags, sizeof(struct flag));
  94.     bwrite(fd, (char *) &dlevel, sizeof dlevel);
  95.     bwrite(fd, (char *) &maxdlevel, sizeof maxdlevel);
  96.     bwrite(fd, (char *) &moves, sizeof moves);
  97.     bwrite(fd, (char *) &u, sizeof(struct you));
  98.     if(u.ustuck)
  99.         bwrite(fd, (char *) &(u.ustuck->m_id), sizeof u.ustuck->m_id);
  100.     bwrite(fd, (char *) pl_character, sizeof pl_character);
  101.     bwrite(fd, (char *) genocided, sizeof genocided);
  102.     bwrite(fd, (char *) fut_geno, sizeof fut_geno);
  103.     savenames(fd);
  104.     for(tmp = 1; tmp <= maxdlevel; tmp++) {
  105.         extern int hackpid;
  106.         extern boolean level_exists[];
  107.  
  108.         if(tmp == dlevel || !level_exists[tmp]) continue;
  109.         glo(tmp);
  110. #ifdef DGK
  111.         printf(" %d", tmp);
  112.         fflush(stdout);
  113. #endif DGK
  114. #ifdef TOS
  115.         if((ofd = open(lock, 0x8000)) < 0) {
  116. #else TOS
  117.         if((ofd = open(lock, 0)) < 0) {
  118. #endif TOS
  119.             if(!hu) pline("Error while saving: cannot read %s.", lock);
  120.             (void) close(fd);
  121.             (void) unlink(SAVEF);
  122.             if(!hu) done("tricked");
  123.             return(0);
  124.         }
  125.         getlev(ofd, hackpid, tmp);
  126.         (void) close(ofd);
  127.         bwrite(fd, (char *) &tmp, sizeof tmp);    /* level number */
  128.         savelev(fd,tmp);            /* actual level */
  129.         (void) unlink(lock);
  130.     }
  131.     (void) close(fd);
  132.     glo(dlevel);
  133.     (void) unlink(lock);    /* get rid of current level --jgm */
  134.     glo(0);
  135.     (void) unlink(lock);
  136.     return(1);
  137. }
  138.  
  139. dorecover(fd)
  140. register fd;
  141. {
  142.     register nfd;
  143.     int tmp;        /* not a register ! */
  144.     unsigned mid;        /* idem */
  145.     struct obj *otmp;
  146.     extern boolean restoring;
  147. #ifdef DGK
  148.     long free, needed;
  149.     free = freediskspace(lock);
  150.     needed = filesize(SAVEF);
  151.     if (free < needed + 10000L) {
  152.         fprintf(stderr, "\n%s\n%s\n%s",
  153.         "There may not be enough disk space to restore your game.  If I",
  154.         "panic while restoring your game, the save file will NOT be deleted.",
  155.         "Should I try to restore your game [y/n] ?");
  156.         if (getchar() != 'y') {
  157.             settty("Be seeing you ...\n");
  158.             exit(0);
  159.         }
  160.     }
  161. #endif DGK
  162.     restoring = TRUE;
  163.     getlev(fd, 0, 0);
  164.     invent = restobjchn(fd);
  165.     for(otmp = invent; otmp; otmp = otmp->nobj)
  166.         if(otmp->owornmask)
  167.             setworn(otmp, otmp->owornmask);
  168.     fcobj = restobjchn(fd);
  169.     fallen_down = restmonchn(fd);
  170.     mread(fd, (char *) &tmp, sizeof tmp);
  171.     if(tmp != getuid()) {        /* strange ... */
  172.         (void) close(fd);
  173.         (void) unlink(SAVEF);
  174.         puts("Saved game was not yours.");
  175.         restoring = FALSE;
  176.         return(0);
  177.     }
  178.     mread(fd, (char *) &flags, sizeof(struct flag));
  179.     mread(fd, (char *) &dlevel, sizeof dlevel);
  180.     mread(fd, (char *) &maxdlevel, sizeof maxdlevel);
  181.     mread(fd, (char *) &moves, sizeof moves);
  182.     mread(fd, (char *) &u, sizeof(struct you));
  183.     if(u.ustuck)
  184.         mread(fd, (char *) &mid, sizeof mid);
  185.     mread(fd, (char *) pl_character, sizeof pl_character);
  186.     mread(fd, (char *) genocided, sizeof genocided);
  187.     mread(fd, (char *) fut_geno, sizeof fut_geno);
  188.     restnames(fd);
  189. #ifdef DGK
  190.     putchar('\n');
  191.     cl_end();
  192.     printf("You got as far as level %d%s.\n", maxdlevel,
  193.         flags.debug ? " in WIZARD mode" : "");
  194.     cl_end();
  195.     printf("Restoring level:");
  196.     fflush(stdout);
  197. #endif DGK
  198.     while(1) {
  199.         if(read(fd, (char *) &tmp, sizeof tmp) != sizeof tmp)
  200.             break;
  201.         getlev(fd, 0, tmp);
  202.         glo(tmp);
  203. #ifdef DGK
  204.         printf(" %d", tmp);
  205.         fflush(stdout);
  206. #endif DGK
  207.         if((nfd = creat(lock, FMASK)) < 0)
  208.             panic("Cannot open level file %s!\n", lock);
  209.         savelev(nfd,tmp);
  210.         (void) close(nfd);
  211.     }
  212.     (void) lseek(fd, 0L, 0);
  213.     getlev(fd, 0, 0);
  214.     (void) close(fd);
  215.     (void) unlink(SAVEF);
  216.     if(Punished) {
  217.         for(otmp = fobj; otmp; otmp = otmp->nobj)
  218.             if(otmp->olet == CHAIN_SYM) goto chainfnd;
  219.         panic("Cannot find the iron chain?");
  220.     chainfnd:
  221.         uchain = otmp;
  222.         if(!uball){
  223.             for(otmp = fobj; otmp; otmp = otmp->nobj)
  224.                 if(otmp->olet == BALL_SYM && otmp->spe)
  225.                     goto ballfnd;
  226.             panic("Cannot find the iron ball?");
  227.         ballfnd:
  228.             uball = otmp;
  229.         }
  230.     }
  231.     if(u.ustuck) {
  232.         register struct monst *mtmp;
  233.  
  234.         for(mtmp = fmon; mtmp; mtmp = mtmp->nmon)
  235.             if(mtmp->m_id == mid) goto monfnd;
  236.         panic("Cannot find the monster ustuck.");
  237.     monfnd:
  238.         u.ustuck = mtmp;
  239.     }
  240. #ifndef QUEST
  241.     setsee();  /* only to recompute seelx etc. - these weren't saved */
  242. #endif QUEST
  243. #ifdef DGK
  244.     gameDiskPrompt();
  245. #endif DGK
  246.     docrt();
  247.     restoring = FALSE;
  248.     return(1);
  249. }
  250.  
  251. struct obj *
  252. restobjchn(fd)
  253. register fd;
  254. {
  255.     register struct obj *otmp, *otmp2;
  256.     register struct obj *first = 0;
  257.     int xl;
  258. #ifdef lint
  259.     /* suppress "used before set" warning from lint */
  260.     otmp2 = 0;
  261. #endif lint
  262.     while(1) {
  263.         mread(fd, (char *) &xl, sizeof(xl));
  264.         if(xl == -1) break;
  265.         otmp = newobj(xl);
  266.         if(!first) first = otmp;
  267.         else otmp2->nobj = otmp;
  268.         mread(fd, (char *) otmp, (unsigned) xl + sizeof(struct obj));
  269.         if(!otmp->o_id) otmp->o_id = flags.ident++;
  270.         otmp2 = otmp;
  271.     }
  272.     if(first && otmp2->nobj){
  273.         impossible("Restobjchn: error reading objchn.");
  274.         otmp2->nobj = 0;
  275.     }
  276.     return(first);
  277. }
  278.  
  279. #ifdef MSDOS
  280. struct monst *
  281. restmonchn(fd)
  282. register fd;
  283. {
  284.     register struct monst *mtmp, *mtmp2;
  285.     register struct monst *first = 0;
  286.     int xl;
  287.     int monsindex;
  288.     extern struct permonst li_dog, dog, la_dog;
  289. #ifdef lint
  290.     /* suppress "used before set" warning from lint */
  291.     mtmp2 = 0;
  292. #endif lint
  293.     while(1) {
  294.         mread(fd, (char *) &xl, sizeof(xl));
  295.         if(xl == -1) break;
  296.         mtmp = newmonst(xl);
  297.         if(!first) first = mtmp;
  298.         else mtmp2->nmon = mtmp;
  299.         mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
  300.         if(!mtmp->m_id)
  301.             mtmp->m_id = flags.ident++;
  302.         monsindex = *((int *)&mtmp->data);
  303.         if (monsindex == -1)
  304.             mtmp->data = &li_dog;
  305.         else if (monsindex == -2)
  306.             mtmp->data = &dog;
  307.         else if (monsindex == -3)
  308.             mtmp->data = &la_dog;
  309.         else
  310.             mtmp->data = &mons[monsindex];
  311.         if(mtmp->minvent)
  312.             mtmp->minvent = restobjchn(fd);
  313.         mtmp2 = mtmp;
  314.     }
  315.     if(first && mtmp2->nmon){
  316.         impossible("Restmonchn: error reading monchn.");
  317.         mtmp2->nmon = 0;
  318.     }
  319.     return(first);
  320. }
  321. #else
  322.  
  323. struct monst *
  324. restmonchn(fd)
  325. register fd;
  326. {
  327.     register struct monst *mtmp, *mtmp2;
  328.     register struct monst *first = 0;
  329.     int xl;
  330.  
  331.     struct permonst *monbegin;
  332.     long differ;
  333.  
  334.     mread(fd, (char *)&monbegin, sizeof(monbegin));
  335.     differ = (char *)(&mons[0]) - (char *)(monbegin);
  336.  
  337. #ifdef lint
  338.     /* suppress "used before set" warning from lint */
  339.     mtmp2 = 0;
  340. #endif lint
  341.     while(1) {
  342.         mread(fd, (char *) &xl, sizeof(xl));
  343.         if(xl == -1) break;
  344.         mtmp = newmonst(xl);
  345.         if(!first) first = mtmp;
  346.         else mtmp2->nmon = mtmp;
  347.         mread(fd, (char *) mtmp, (unsigned) xl + sizeof(struct monst));
  348.         if(!mtmp->m_id)
  349.             mtmp->m_id = flags.ident++;
  350.         mtmp->data = (struct permonst *)
  351.             ((char *) mtmp->data + differ);
  352.         if(mtmp->minvent)
  353.             mtmp->minvent = restobjchn(fd);
  354.         mtmp2 = mtmp;
  355.     }
  356.     if(first && mtmp2->nmon){
  357.         impossible("Restmonchn: error reading monchn.");
  358.         mtmp2->nmon = 0;
  359.     }
  360.     return(first);
  361. }
  362. #endif MSDOS
  363.